package com.nnnu.orange.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.houbb.sensitive.word.core.SensitiveWordHelper;
import com.nnnu.orange.constant.MessageConstants;
import com.nnnu.orange.constant.StatusConstants;
import com.nnnu.orange.exception.ObjectException;
import com.nnnu.orange.exception.TimeException;
import com.nnnu.orange.mapper.BooksMapper;
import com.nnnu.orange.mapper.CommentsMapper;
import com.nnnu.orange.pojo.dto.*;
import com.nnnu.orange.pojo.entity.Comments;
import com.nnnu.orange.pojo.vo.CommentsVo;
import com.nnnu.orange.result.PageResult;
import com.nnnu.orange.service.ICommentsService;
import com.nnnu.orange.utils.ThreadLocalUtil;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Objects;

/**
 * <p>
 * 存储图书评论的详细信息 服务实现类
 * </p>
 *
 * @author zk
 * @since 2024-11-07
 */

@Service
@Transactional
public class CommentsServiceImpl extends ServiceImpl<CommentsMapper, Comments> implements ICommentsService {

    /**
     * 分页查询图书评论
     *
     * @param queryDto dto
     * @return 分页列表
     */
    @Override
    public PageResult<CommentsVo> list(@NotNull CommentQueryDto queryDto) {
        // 验证并处理时间范围
        if (queryDto.getStartTime() != null && queryDto.getEndTime() != null &&
                queryDto.getEndTime().isBefore(queryDto.getStartTime())) {
            throw new TimeException(MessageConstants.BEFORE);
        }
        // 设置时间边界
        LocalDateTime start = queryDto.getStartTime() != null ?
                queryDto.getStartTime().atStartOfDay() : null;
        LocalDateTime end = queryDto.getEndTime() != null ?
                queryDto.getEndTime().atTime(LocalTime.MAX) : null;

        // 分页查询
        Page<CommentsVo> page = new Page<>(queryDto.getPageNum(), queryDto.getPageSize());
        Page<CommentsVo> commentsVoPage = baseMapper.selectCommentsPage(page, queryDto, start, end);

        return new PageResult<>(commentsVoPage.getTotal(), commentsVoPage.getRecords());
    }


    /**
     * 管理员新增图书评论
     *
     * @param commentDto dto
     * @return 是否添加成功
     */
    @Override
    public Boolean save(@NotNull CommentDto commentDto) {
        //如果存在违规语句不给添加
        if (SensitiveWordHelper.contains(commentDto.getComment())) {
            throw new ObjectException(SensitiveWordHelper.replace(commentDto.getComment(), '*') + "存在违规不允许评论");
        }
        Comments comments = BeanUtil.copyProperties(commentDto, Comments.class);
        comments.setCreatedAt(LocalDateTime.now());
        comments.setAdminId(Math.toIntExact(ThreadLocalUtil.getId()));
        return save(comments);
    }

    /**
     * 修改某个图书的置顶情况
     *
     * @param topDto dto
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateBookCommentTop(@NotNull CommentTopDto topDto) {
        Integer status = topDto.getIsTop();
        Comments comments = baseMapper.selectOne(new LambdaQueryWrapper<Comments>()
                .eq(Comments::getCommentId, topDto.getCommentId())
                .eq(Comments::getBookId, topDto.getBookId())
                .notIn(Comments::getStatus, StatusConstants.THREE, StatusConstants.TWO, StatusConstants.ZERO));
        if (comments == null) {
            throw new ObjectException(MessageConstants.COMMENTS_TOP_UPDATE_ERR);
        }
        if (Objects.equals(status, StatusConstants.ONE)) {
            Comments topComment = baseMapper.selectOne(new LambdaQueryWrapper<Comments>()
                    .eq(Comments::getBookId, topDto.getBookId())
                    .eq(Comments::getIsTop, StatusConstants.ONE));
            if (topComment != null) {
                topComment.setIsTop(StatusConstants.ZERO);
                baseMapper.updateById(topComment);
            }
            comments.setIsTop(StatusConstants.ONE);
            baseMapper.updateById(comments);
        } else if (Objects.equals(status, StatusConstants.ZERO)) {
            comments.setIsTop(StatusConstants.ZERO);
            baseMapper.updateById(comments);
        } else {
            throw new ObjectException(MessageConstants.NULL);
        }
    }

    /**
     * 修改某个图书下的评论状态
     *
     * @param statusDto dto
     */
    @Override
    public void updateBookCommentStatus(@NotNull CommentStatusDto statusDto) {
        Comments comments = getOne(new LambdaQueryWrapper<Comments>()
                .eq(Comments::getCommentId, statusDto.getCommentId()));
        if (comments == null) {
            throw new ObjectException(MessageConstants.COMMENTS_NULL);
        }
        Integer currentStatus = comments.getStatus();
        Integer newStatus = statusDto.getStatus();
        if (Objects.equals(currentStatus, newStatus)) {
            throw new ObjectException(MessageConstants.STATUS_EQUAL);
        }
        if (Objects.equals(currentStatus, StatusConstants.TWO) || Objects.equals(currentStatus, StatusConstants.THREE)) {
            throw new ObjectException(MessageConstants.COMMENTS_STATUS_UPDATE_ERR);
        }
        comments.setStatus(newStatus);
        baseMapper.updateById(comments);
    }

    /**
     * 修改图书某条评论
     *
     * @param commentDto dto
     */
    @Override
    public void updateById(@NotNull CommentUpdateDto commentDto) {
        Comments comments = getById(commentDto.getCommentId());
        //检测评论是否成存在
        if (comments == null) {
            throw new ObjectException(MessageConstants.COMMENT_NULL);
        }
        // 检查评论状态是否允许修改
        Integer status = comments.getStatus();
        if (Objects.equals(status, StatusConstants.THREE) || Objects.equals(status, StatusConstants.TWO)) {
            throw new ObjectException(MessageConstants.COMMENTS_STATUS_UPDATE_ERR);
        }
        // 检查并替换敏感词，若存在敏感词则不允许修改
        String updatedComment = commentDto.getComment();
        if (SensitiveWordHelper.contains(updatedComment)) {
            throw new ObjectException(SensitiveWordHelper.replace(updatedComment, '*') + " 存在违规内容，修改被拒绝");
        }
        baseMapper.updateById(comments.setComment(updatedComment));
    }
}
